"""
FastAPI main application entry point for AncientSeeker

Ancient Chinese literature AI exploration platform
"""

from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import JSONResponse
import os
import logging
from pathlib import Path

# 设置日志
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

from app.config import settings
from app.database import engine, Base, SessionLocal
from app import models  # noqa: F401  # Import to register models
from app.api import auth, books, ai_image, chat_sessions, exploration_nodes
from app.services.book_service import book_service
from app.models.book_model import Book
from app.models.user import User
from app.utils.auth import get_password_hash
from app.seed.explore_seed import seed_exploration_if_empty

# Create database tables
Base.metadata.create_all(bind=engine)

# Initialize FastAPI app
app = FastAPI(
    title="AncientSeeker API",
    description="AI-powered ancient Chinese literature exploration platform",
    version="0.1.0",
    docs_url="/docs",
    redoc_url="/redoc",
)

# CORS middleware configuration
app.add_middleware(
    CORSMiddleware,
    # 使用 allow_origin_regex 以便匹配局域网 IP（如 192.168.x.x:5173 / 10.x.x.x:5173）
    allow_origin_regex=r"^https?://(localhost|127\.0\.0\.1|10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|192\.168\.[0-9]{1,3}\.[0-9]{1,3})(:[0-9]{2,5})?$",
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
    allow_headers=["*"],
)


# 添加调试中间件
@app.middleware("http")
async def debug_cors(request: Request, call_next):
    if request.method == "OPTIONS":
        logger.debug(f"OPTIONS request from {request.headers.get('origin')}")
        logger.debug(f"Request headers: {dict(request.headers)}")

    response = await call_next(request)

    if request.method == "OPTIONS":
        logger.debug(f"Response status: {response.status_code}")
        logger.debug(f"Response headers: {dict(response.headers)}")

    return response


# Mount static files with absolute path (more robust)
try:
    images_dir = Path(__file__).resolve().parent.parent / "data" / "images"
    if images_dir.exists():
        logger.debug(f"Preparing to mount static directories under {images_dir}")
        app.mount("/static", StaticFiles(directory=str(images_dir)), name="static")
        # 新增：用户隔离生成图像目录 /static/generated/<uid>/<file>
        gen_dir = images_dir / "generated"
        gen_dir.mkdir(exist_ok=True)
        if gen_dir.exists():
            logger.debug(f"Mount /static/generated -> {gen_dir}")
        app.mount(
            "/static/generated",
            StaticFiles(directory=str(gen_dir)),
            name="static_generated",
        )
        # 兼容旧代码曾返回 /static/images/<file> 的情况，额外挂载同目录到 /static/images
        # 这样历史记录中的 URL 仍能访问
        app.mount(
            "/static/images",
            StaticFiles(directory=str(images_dir)),
            name="static_legacy",
        )
        logger.debug(f"Mounted /static -> {images_dir}")
    else:
        logger.warning(f"Images directory not found: {images_dir}")

    # 挂载头像目录
    avatars_dir = Path(__file__).resolve().parent.parent / "data" / "avatars"
    avatars_dir.mkdir(parents=True, exist_ok=True)
    if avatars_dir.exists():
        app.mount("/avatars", StaticFiles(directory=str(avatars_dir)), name="avatars")
        logger.debug(f"Mounted /avatars -> {avatars_dir}")
except Exception as e:
    logger.error(f"Failed to mount static directories: {e}")

# Include API router(s)
app.include_router(auth.router, prefix="/api/auth", tags=["Auth"])
app.include_router(books.router, prefix="/api/books", tags=["Books"])
app.include_router(ai_image.router, prefix="/api/ai", tags=["AI Image"])
app.include_router(chat_sessions.router, prefix="/api", tags=["Chat (New)"])
app.include_router(exploration_nodes.router, prefix="/api/explore", tags=["Explore"])


@app.get("/")
async def root():
    """Root endpoint with welcome message"""
    return {
        "message": "Welcome to AncientSeeker API",
        "description": "AI-powered ancient Chinese literature exploration platform",
        "version": "0.1.0",
        "docs": "/docs",
    }


@app.get("/health")
async def health_check():
    """Health check endpoint"""
    return {"status": "healthy", "service": "AncientSeeker API"}


@app.on_event("startup")
def startup_load_books_if_empty():
    """在应用启动时自动导入书籍（仅当数据库还没有书籍记录时）。"""
    db = SessionLocal()
    try:
        book_count = db.query(Book).count()
        if book_count == 0:
            logger.info("No books found in database. Auto-importing JSON book data...")
            summary = book_service.load_books_from_json(db)
            logger.info(
                "Book import summary: directory=%s loaded=%s updated=%s skipped=%s errors=%s",
                summary.get("directory"),
                summary.get("loaded"),
                summary.get("updated"),
                summary.get("skipped"),
                len(summary.get("errors", [])),
            )
        else:
            logger.debug(f"Startup skip book import (existing count={book_count})")

        # Normalize legacy cover paths (migrate old '/images/books/xxx.jpg' to new 'bookid_cover.png')
        try:
            images_dir = Path(__file__).resolve().parent.parent / "data" / "images"
            books_all = db.query(Book).all()
            changed = 0
            for b in books_all:
                cover_value = getattr(b, "cover", None)
                cover_str = (
                    cover_value if isinstance(cover_value, str) else (cover_value or "")
                )
                # 已经是简洁文件名并且存在 => 跳过
                if (
                    cover_str
                    and "/" not in cover_str
                    and (images_dir / cover_str).exists()
                ):
                    continue
                candidate = f"{b.book_id}_cover.png"
                new_cover = None
                if (images_dir / candidate).exists():
                    if cover_str != candidate:
                        new_cover = candidate
                else:
                    base_id = b.book_id
                    for alt in [
                        f"{base_id}_cover.jpg",
                        f"{base_id}-cover.jpg",
                        f"{base_id}-cover.png",
                    ]:
                        if (images_dir / alt).exists():
                            if cover_str != alt:
                                new_cover = alt
                            break
                if new_cover:
                    setattr(b, "cover", new_cover)
                    changed += 1
            if changed:
                db.commit()
                logger.info(f"Normalized {changed} book cover filenames during startup")
        except Exception as ce:
            logger.warning(f"Cover normalization skipped: {ce}")

        # Ensure an admin user exists (lightweight check)
        admin_exists = db.query(User).filter(User.username == "admin").first()
        if not admin_exists:
            admin_user = User(
                username="admin",
                password_hash=get_password_hash("admin123"),
                is_admin=True,
                is_guest=False,
                is_active=True,
            )
            db.add(admin_user)
            db.commit()
            logger.info(
                "Default admin user created (username=admin / password=admin123)"
            )

        # ---- Seed Exploration Mode demo data (delegated) ----
        try:
            summary = seed_exploration_if_empty(db)
            if any(summary.values()):
                logger.info(
                    "Exploration seed: nodes=%s quests=%s achievements=%s",
                    summary.get("nodes"),
                    summary.get("quests"),
                    summary.get("achievements"),
                )
        except Exception as se:
            logger.warning(f"Exploration seed skipped: {se}")
    except Exception as e:
        logger.error(f"Startup initialization failed: {e}")
    finally:
        db.close()


if __name__ == "__main__":
    import uvicorn

    print("Settings:", settings)
    uvicorn.run(
        "main:app", host=settings.HOST, port=settings.PORT, reload=settings.DEBUG
    )
